#pragma once
#include "exchange.hpp"
#include "msgqueue.hpp"
#include "binding.hpp"
#include "message.hpp"
#include <google/protobuf/map.h>



class VirtualHost
{
public:
    using Ptr = std::shared_ptr<VirtualHost>;
    VirtualHost(const std::string& hostName, const std::string& basedir, const std::string& dbfile)
        :_name(hostName)
        ,_exchangeManagerPtr(std::make_shared<ExchangeManager>(dbfile))
        ,_msgQueueManagerPtr(std::make_shared<MsgQueueManager>(dbfile))
        ,_bindingManagerPtr(std::make_shared<BindingManager>(dbfile))
        ,_messageManagerPtr(std::make_shared<MessageManager>(basedir))
    {
        auto msgqs = _msgQueueManagerPtr->getAllMsgQueue();
        for(auto& msgq : msgqs)                 //消息的recover，消息的recovery是借助队列名
            _messageManagerPtr->initQueueMessage(msgq.first);
    }

    void declareExchange(const std::string& exchangeName, ExchangeType ExchangeType, bool exchangeDurable, bool exchangeAutoDelete, const google::protobuf::Map<std::string, std::string>& exchangeArgs)
    {
        _exchangeManagerPtr->declareExchange(exchangeName, ExchangeType, exchangeDurable, exchangeAutoDelete, exchangeArgs);
    }    
    void deleteExchange(const std::string& exchangeName)
    {
        _exchangeManagerPtr->deleteExchange(exchangeName);
        _bindingManagerPtr->removeExchangeBinding(exchangeName);        //对应的绑定信息也要删掉
    }
    bool existsExchange(const std::string& exchangeName)
    {
        return _exchangeManagerPtr->exists(exchangeName);
    }
    Exchange::Ptr selectExchange(const std::string& exchangeName)
    {
        return _exchangeManagerPtr->selectExchange(exchangeName);
    }

    void declareMsgQueue(const std::string& msgQueueName, bool msgQueuedurable, bool msgQueueexclusive, bool msgQueueautoDelete, const google::protobuf::Map<std::string, std::string>& msgQueueargs)
    {
        _messageManagerPtr->initQueueMessage(msgQueueName);//这个队列的消息
        _msgQueueManagerPtr->declareMsgQueue(msgQueueName, msgQueuedurable, msgQueueexclusive, msgQueueautoDelete, msgQueueargs);
    }
    void deleteMsgQueue(const std::string& msgQueueName)
    {
        _msgQueueManagerPtr->deleteMsgQueue(msgQueueName);  
        _bindingManagerPtr->removeMsgQueueBinding(msgQueueName);        //删除队列的绑定信息
        _messageManagerPtr->destoryQueueMessage(msgQueueName);          //删除队列的消息
    }
    bool existsMsgQueue(const std::string& msgQueueName)
    {
        return _msgQueueManagerPtr->exists(msgQueueName);
    }
    std::unordered_map<std::string, MsgQueue::Ptr> getAllMsgQueue()         //新增一个获取所有队列名字
    {
        return _msgQueueManagerPtr->getAllMsgQueue();
    }
    bool bind(const std::string& exchangeName, const std::string& msgQueueName, const std::string& key)
    {
        Exchange::Ptr exchangePtr = _exchangeManagerPtr->selectExchange(exchangeName);
        if(exchangePtr.get() == nullptr)
        {
            DLOG("exchange:%s 没有, 无法绑定", exchangeName.c_str());
            return false;
        }
        MsgQueue::Ptr msgqueuePtr = _msgQueueManagerPtr->selectMsgQueue(msgQueueName);
        if(msgqueuePtr.get() == nullptr)
        {
            DLOG("msgQueue:%s 没有, 无法绑定", exchangeName.c_str());
            return false;
        }
        return _bindingManagerPtr->bind(exchangeName, msgQueueName, key, exchangePtr->durable && msgqueuePtr->durable);
    }
    void unBind(const std::string& exchangeName, const std::string& msgQueueName)
    {
        _bindingManagerPtr->unBind(exchangeName, msgQueueName);
    }
    MsgQueueBindingMap exchangeBindings(const std::string& exchangeName)
    {
        return _bindingManagerPtr->getExchangeBindings(exchangeName);
    }
    bool existsBinding(const std::string& exchangeName,const std::string& msgQueueName)
    {
        return _bindingManagerPtr->exists(exchangeName, msgQueueName);
    }
    void basicPublish(const std::string& msgQueueName, BasicProperty* bp, const std::string& body)
    {
        // _messageManagerPtr->initQueueMessage(msgQueueName);
        MsgQueue::Ptr msgQueuePtr = _msgQueueManagerPtr->selectMsgQueue(msgQueueName);
        if(msgQueuePtr.get() == nullptr)
        {
            DLOG("msgQueue:%s 没有, 无法添加消息", msgQueueName.c_str());
            return;     
        }
        DLOG("怎么，没有进去吗msgQueuePtr->durable:%d", msgQueuePtr->durable);          /////////////////////////////////////////////
        _messageManagerPtr->insert(msgQueueName, bp, body, msgQueuePtr->durable); //消息添加到队列中
    }
    wzf::MessagePtr basicConsume(const std::string& qname)
    {
        return _messageManagerPtr->front(qname);
    }
    void basicAck(const std::string& queueName, const std::string& msgID)
    {
        _messageManagerPtr->ack(queueName, msgID);
    }
    
    void clear()
    {
        _exchangeManagerPtr->clear();
        _msgQueueManagerPtr->clear();
        _bindingManagerPtr->clear();
        _messageManagerPtr->clear();
    }
private:
    std::string _name;
    ExchangeManager::Ptr _exchangeManagerPtr;
    MsgQueueManager::Ptr _msgQueueManagerPtr;
    BindingManager::Ptr _bindingManagerPtr;
    MessageManager::Ptr _messageManagerPtr;
};